/**
* 
* @author Xiaoyu Zhang
*/
#ifndef PBVP_VOLUME_REG3_H
#define PBVP_VOLUME_REG3_H

#include <iostream>
#include <vector>

#include "tetra.h"
#include "contourtree.h"
#include "contreeconstructor.h"
#include "../data/reg3dvolumedata.h"

namespace PBVP {
	/// A Class build contour tree from regular 3D volume data  
	class ConTreeConstructorReg3D : public ConTreeConstructor
	{
	public:
		/**
		 * Constructor
		 */
		ConTreeConstructorReg3D(Reg3DVolumeData* pData);
		
		/** 
		 * Destructor
		 */
		virtual ~ConTreeConstructorReg3D(void);

	protected:
		/********************************************************************/
		/* Overridden virtual functions                                     */
		/********************************************************************/
		///
		virtual float getCPValue(int id) const {
			return m_pData->getValue(id, 0);
		}

		/// Number of vertices in the data
		virtual int getNumOfCPs() const {
			return m_Dim[0]*m_Dim[1]*m_Dim[2];
		}

		/// Construct the list of critical points with information for computing topology
		/**
		* This function is useful for computing the Betti numbers of a
		* contour.
		*/
		virtual void calcLUStars();

		///
		virtual bool isMinimum(const CriticalPoint& cp);

		///
		virtual bool isMaximum(const CriticalPoint& cp);

		///
		virtual int getNeighbors(int vid, int* neighbors);

		///
		virtual int maxNeighborNumbers() const { return 14; }

		/** 
		 * Check if a vertex index is valid
		 * 
		 * @param idx
		 * 
		 * @return bool
		 */
		bool isValidIndex(int idx[3]) {
			return(idx[0] >= 0 && idx[1] >= 0 && idx[2] >= 0 &&
				idx[0] < m_Dim[0] && idx[1] < m_Dim[1] && idx[2] < m_Dim[2]);
		}

	protected:
		///
		unsigned int m_Dim[3];
		///
		float m_Orig[3], m_Span[3];

		/// volumetric function for constructing the CT 
		/** 
		 * It may have more than one functions. The first function defines
		 * the shape and the rest are property functions
		 */
		Reg3DVolumeData*  m_pData;

		// char* touched;					// used for volume computation

		/** 
		 * Find indices of v1, v2, and v3 in the p_map and output them
		 * in increasing order. 
		 * 
		 * @param p_map
		 * @param v1
		 * @param v2
		 * @param v3
		 * @param ordered
		 */
		void orderTriangleVerts(int* p_map, int v1, int v2, int v3, int ordered[3]);

		/** 
		 * Find indices of v1, v2, v3, and v4 in the p_map and output them
		 * in increasing order.
		 * 
		 * @param p_map
		 * @param v1
		 * @param v2
		 * @param v3
		 * @param v4
		 * @param ordered
		 */
		void orderTetrahedronVerts(int* p_map, int v1, int v2, int v3, int v4, int ordered[4]);

		/** 
		 * 
		 * 
		 * @param p_v
		 * @param p_map
		 * @param v1
		 * @param v2
		 * @param v3
		 * @param bounflag
		 */
		void LUTriangle(std::vector<CriticalPoint>* p_v, int *p_map, int v1, int v2, int v3, bool bounflag);

		/** 
		 * 
		 * 
		 * @param p_v
		 * @param p_map
		 * @param v1
		 * @param v2
		 * @param v3
		 * @param v4
		 */
		void LUTetrahedron(std::vector<CriticalPoint>* p_v, int *p_map, int v1, int v2, int v3, int v4);

	};
}
#endif
